﻿#define DEBUG

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Threading;
using System.Net;
using System.Diagnostics;
using StaProject.Etc;

namespace StaProject.Logic
{
    class Program
    {

        /// <summary>
        /// Хранилище данных
        /// </summary>
        public static VKEntities vk;

        public static Random rnd = new Random();
        
        /// <summary>
        /// Список прокси серверов
        /// </summary>
        public static List<string> psArr = new List<string>();

        /// <summary>
        /// Метод парсит html страницу и извлекает номер, имя и фамилию
        /// </summary>
        /// <param name="text">HTML страница</param>
        /// <returns></returns>
        public List<FOAF3> GetListFoaf(string text)
        {
            Regex rg = new Regex("(<a href=\"id[0-9]+\">(([0-9 ]+)\\(([0-9a-zA-Zа-яА-Я \\-_-[<>]]+)\\)))");
            MatchCollection match = rg.Matches(text);

            List<FOAF3> listRes = new List<FOAF3>();

            foreach (Match m in match)
            {
                string number = m.Groups[3].Value.Replace(" ", "");
                string fi = m.Groups[4].Value.Trim();
                int indexS = fi.IndexOf(' ');

                if (indexS != -1)
                {
                    string name = fi.Substring(0, indexS);
                    string fam = fi.Remove(0, indexS + 1);
                    if (name.Length < 50 && fam.Length < 50)
                        listRes.Add(new FOAF3() { IndexVkontakte = number, FirstName = name, SecondName = fam });
                }
            }
        
            return listRes;
        }

        /// <summary>
        /// Заполняем список проксей
        /// </summary>
        public static void FillProxyList()
        {
            StreamReader sr = new StreamReader(@"C:\temp\Proxy.txt");
            psArr.AddRange(sr.ReadToEnd().Split(new char[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries));
            sr.Close();
        }

        /// <summary>
        /// Берём прокси сервер из списка
        /// </summary>
        /// <returns>адрес прокси сервера</returns>
        public string getProxy()
        {
            string res = "";
            
            lock (psArr)
            {
                if (psArr.Count == 0)
                {
                    FillProxyList();        
                }

                res = psArr[0];
                psArr.RemoveAt(0);
                psArr.Add(res);
            }

            return res;
        }

        public string GetResponse(int i, int j, int k)
        {
            string proxy = getProxy();
            
            try
            {
                WebProxy wp = new WebProxy();
                wp.Address = new Uri(@"http://" + proxy);
                string strUrl = String.Format("http://vkontakte.ru/catalog.php?selection={0}-{1}-{2}", i, j, k);
                WebRequest wr = WebRequest.Create(strUrl);
                
                //можно и без этого
                wr.Proxy = wp;

#if DEBUG
                Debug.WriteLine("Делаем запрос {0} {1} {2}", i, j, k);
#endif

                WebResponse wres = wr.GetResponse();
                
                StreamReader sr = new StreamReader(wres.GetResponseStream(), Encoding.GetEncoding("windows-1251"));
                string text = sr.ReadToEnd();

                if (text.IndexOf("Каталог пользователей ВКонтакте") < 0) throw new FormatException();
                
                return text;
            }
            catch
            {
                if (!System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable())
                {
                    while (!System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable())
                    {
#if DEBUG 
                        Debug.WriteLine("________!!!ВНИМАНИЕ!!! Нет интернет подключения");
#endif
                        Thread.Sleep(3000);
                    }
                }
                else
                {
                    psArr.Remove(proxy);
#if DEBUG
                    Debug.WriteLine("Не удалось сделать запрос {0} {1} {2} {3}", i, j, k, psArr.Count);
#endif
                }

                return GetResponse(i, j, k);
            }
        }

        static void Main(string[] args)
        {
            

            FillProxyList();
            
            Console.WriteLine("start I");
            int sI = int.Parse(Console.ReadLine());

            Console.WriteLine("end I");
            int eI = int.Parse(Console.ReadLine());

            Console.WriteLine("start J");
            int sJ = int.Parse(Console.ReadLine());

            Console.WriteLine("end I");
            int eJ = int.Parse(Console.ReadLine());

            
            Console.WriteLine("end K");
            int eK = int.Parse(Console.ReadLine());

            for (int i = sI; i < eI; i++)
            {
                for (int j = (i==sI)?sJ:0; (i == eI) ? (j < eJ) : (j < 100); j++)
                {
                 
                    List<FOAF3> li = new List<FOAF3>();
                    Action<int> act = kIndex =>
                    {
                        Program p = new Program();

                        if (kIndex > 99) return;
                        if (i == eI && j == eJ && kIndex > eK) return;

                        string res = p.GetResponse(i, j, kIndex);

#if DEBUG
                        Debug.WriteLine("Парсим страницу {0} {1} {2}", i, j, kIndex);
#endif
      
                        var a = p.GetListFoaf(res);
                        
                        lock (li)
                        {
                            li.AddRange(a);
                        }

                    };


                    Parallel.For(0, 99, x => act(x));

                    using (vk = new VKEntities())
                    {

                        foreach (var x in li)
                        {
                            if (x != null)
                                vk.AddToFOAF3(x);
                        }

                        if (vk.Connection.State == System.Data.ConnectionState.Closed)
                        {
                            vk.Connection.Open();
                        }
#if DEBUG
                        Debug.WriteLine("Добавляем в БД {0} {1} ", i, j);
#endif
                        vk.SaveChanges();
                        vk.AcceptAllChanges();
                    }
                }
            }

        }
    }
}
